package cn.com.srit.service.impl;

import cn.com.srit.entity.DeptEntity;
import cn.com.srit.repository.DeptRepository;
import cn.com.srit.service.DeptService;
import cn.com.srit.util.BeanUtils;
import cn.com.srit.util.DateUtils;
import cn.com.srit.util.PageDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptRepository deptRepository;

    @Override
    public List<DeptEntity> findAll(DeptEntity template) {
        return deptRepository.findAll(new Specification<DeptEntity>() {
            @Override
            public Predicate toPredicate(Root<DeptEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return getCriteriaPredicate(root, criteriaQuery, criteriaBuilder, template);
            }
        });
    }

    @Override
    public Page<DeptEntity> findAllWithPage(DeptEntity template, PageDetail page) {
        return deptRepository.findAll(new Specification<DeptEntity>() {
            @Override
            public Predicate toPredicate(Root<DeptEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                return getCriteriaPredicate(root, criteriaQuery, criteriaBuilder, template);
            }
        }, new PageRequest(page.getPageNumber(), page.getPageSize(), new Sort(page.getSortOrder(), page.getSortName())));
    }

    @Override
    @Transactional
    public String save(DeptEntity dept) {
        String result;
        try {
            if (!StringUtils.hasText(dept.getId())) {
                dept.setCreateTime(DateUtils.getCurrentTime());
                dept.setState(true);
            } else {
                BeanUtils.copyNullProperties(deptRepository.findOne(dept.getId()), dept);
            }
            deptRepository.saveAndFlush(dept);
            result = "success";
        } catch (Exception e) {
            result = "error";
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

    @Override
    @Transactional
    public String delete(String[] ids) {
        String result;
        try {
            for (int i = 0; i < ids.length; i++) {
                deptRepository.delete(ids[i]);
            }
            result = "success";
        } catch (Exception e) {
            result = "error";
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

    private Predicate getCriteriaPredicate(Root<DeptEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder, DeptEntity template) {
        List<Predicate> predicateList = new ArrayList<>();
        if (StringUtils.hasText(template.getPid())) {
            predicateList.add(criteriaBuilder.equal(root.get("pid").as(String.class), template.getPid()));
        }
        if (StringUtils.hasText(template.getCode())) {
            predicateList.add(criteriaBuilder.like(root.get("code").as(String.class), "%" + template.getCode() + "%"));
        }
        if (StringUtils.hasText(template.getName())) {
            predicateList.add(criteriaBuilder.like(root.get("name").as(String.class), "%" + template.getName() + "%"));
        }
        return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
    }
}
